import { EStorage, EStorageKey } from '../enums/storage.enum';

export interface IStorageSuccess { value: any, storage: any }

export interface IStorageMethods {
    /** 异步获取缓存中的数据 */
    get: (key?: EStorage) => Promise<IStorageSuccess>
    /** 同步步获取缓存中的数据 */
    getSync: (key?: EStorage) => IStorageSuccess;
    /** 异步设置缓存中的数据 */
    set: (key: EStorage, value: any) => Promise<boolean>;
    /** 同步设置缓存中的数据 */
    setSync: (key: EStorage, value: any) => boolean;
    /** 异步清除缓存中的某条数据 */
    remove: (key: EStorage) => Promise<boolean>;
    /** 同步清除缓存中的某条数据 */
    removeSync: (key: EStorage) => boolean;
    /** 置空缓存 */
    clear: () => void;
}

class StorageService implements IStorageMethods {
    private key: EStorageKey;
    private defaultStorage: object;
    /** key：缓存id，defaultStorage默认key对应的缓存数据 */
    constructor(key: EStorageKey, defaultStorage: Object = {}) {
        this.key = key;
        this.defaultStorage = defaultStorage;
        try {
            const storage = uni.getStorageSync(key);
            if (!storage) {
                uni.setStorageSync(key, this.stringifyJson(defaultStorage))
            }
        } catch (e) { }
    }
    parseJson(json: string) { return JSON.parse(json) }
    stringifyJson(json: Record<string, any>) { return JSON.stringify(json) }
    get(key?: EStorage): Promise<IStorageSuccess> {
        const _this = this;
        return new Promise((resolve, reject) => {
            uni.getStorage({
                key: this.key,
                success({ data }) {
                    const json = _this.parseJson(data || "{}");
                    resolve({ value: key ? Reflect.get(json, key) : null, storage: json })
                },
                fail() {
                    resolve({ value: null, storage: null })
                }
            })
        })
    }
    getSync(key?: EStorage): IStorageSuccess {
        try {
            const value = uni.getStorageSync(this.key) || "{}";
            const json = this.parseJson(value);
            if (json && key) return { value: Reflect.get(json, key), storage: json }
            return { value: null, storage: json }
        } catch (e) {
            return { value: null, storage: null }
        }
    }
    set(key: EStorage, value: any): Promise<boolean> {
        return new Promise((resolve, reject) => {
            const { storage } = this.getSync();
            if (storage) {
                Reflect.set(storage, key, value);
                uni.setStorage({
                    key: this.key,
                    data: this.stringifyJson(storage),
                    success() {
                        resolve(true)
                    },
                    fail() {
                        resolve(false)
                    }
                })
            } else {
                resolve(false)
            }
        })
    }
    setSync(key: EStorage, value: any): boolean {
        const { storage } = this.getSync();
        if (storage) {
            Reflect.set(storage, key, value);
            try {
                uni.setStorageSync(this.key, this.stringifyJson(storage))
                return true;
            } catch (e) {
                return false;
            }
        }
        return false;
    }
    remove(key: EStorage): Promise<boolean> {
        return new Promise((resolve, reject) => {
            const { storage } = this.getSync();
            if (storage) {
                Reflect.deleteProperty(storage, key);
                uni.setStorage({
                    key: this.key,
                    data: this.stringifyJson(storage),
                    success() { resolve(true) },
                    fail() { resolve(false) }
                })
            } else {
                resolve(false)
            }
        })
    }
    removeSync(key: EStorage): boolean {
        try {
            const { storage } = this.getSync();
            if (storage) {
                Reflect.deleteProperty(storage, key);
                uni.setStorageSync(this.key, this.stringifyJson(storage));
                return true;
            } else return false;
        } catch (e) {
            return false
        }
    }
    clear(): boolean {
        try {
            uni.setStorageSync(this.key, '{}')
            return true
        } catch (e) {
            return false
        }
    }
}

export default new StorageService(EStorageKey.YUE_BA)